//package com.dmz.proxy.controller;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.core.io.Resource;
//import org.springframework.http.*;
//import org.springframework.stereotype.Controller;
//import org.springframework.util.LinkedMultiValueMap;
//import org.springframework.util.MultiValueMap;
//import org.springframework.util.StringUtils;
//import org.springframework.web.bind.annotation.*;
//import org.springframework.web.client.RestTemplate;
//import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
//import org.springframework.web.util.HtmlUtils;
//
//import javax.servlet.http.HttpServletRequest;
//import java.net.URLEncoder;
//import java.nio.charset.StandardCharsets;
//import java.util.Objects;
//import java.util.regex.Pattern;
//
///**
// * @author lee
// */
//@Controller
//@RequestMapping("${target.mapping}")
//public class ProxyController {
//
//    private static final Logger log = LoggerFactory.getLogger(ProxyController.class);
//
//    // 安全正则表达式
//    private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_\\-.\\(\\)\\[\\] ]+$");
//
//    // 安全的HTTP头名称正则（字母、数字、连字符）
//    private static final Pattern SAFE_HEADER_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9\\-]+$");
//    // 安全的HTTP头值正则（排除控制字符）
//    private static final Pattern SAFE_HEADER_VALUE_PATTERN = Pattern.compile("^[\\x20-\\x7E\\x09]*$");
//
//    // 安全的内容类型正则
//    private static final Pattern SAFE_CONTENT_TYPE_PATTERN = Pattern.compile("^[a-zA-Z0-9_\\-+/.;= ]*$");
//
//    @Autowired
//    private RestTemplate restTemplate;
//
//    @Value("${target.url}")
//    private String targetUrl;
//
//    @Value("${target.mapping}")
//    private String mapping;
//
//    // 所有GET请求处理方法
//    @GetMapping(value = {"/system/acct/**", "/system/account2/**", "/system/history/**", "/system/today/**", "/captchaImage", "/getInfo", "/getRouters"})
//    @ResponseBody
//    public ResponseEntity<String> forwardGetDataRequest(
//            @RequestHeader HttpHeaders headers,
//            @RequestBody(required = false) String requestBody,
//            HttpServletRequest request) {
//
//        HttpHeaders sanitizedHeaders = sanitizeHeaders(headers);
//        HttpEntity<String> entity = new HttpEntity<>(requestBody, sanitizedHeaders);
//
//        String url = getUrl(request.getServletPath());
//        log.info("forward:{}", url);
//        HttpMethod method = HttpMethod.resolve(request.getMethod());
//        assert method != null;
//
//        ResponseEntity<String> response = restTemplate.exchange(url, method, entity, String.class);
//        return sanitizeResponse(response);
//    }
//
//    // POST请求处理方法
//    @ResponseBody
//    @PostMapping(value = {"/system/account2", "/login", "/logout"})
//    public ResponseEntity<String> forwardPostDataRequest(
//            @RequestHeader HttpHeaders headers,
//            @RequestBody(required = false) String requestBody,
//            HttpServletRequest request) {
//
//        HttpHeaders sanitizedHeaders = sanitizeHeaders(headers);
//        String url = getUrl(request.getServletPath());
//        HttpMethod method = HttpMethod.resolve(request.getMethod());
//        HttpEntity<String> entity = new HttpEntity<>(requestBody, sanitizedHeaders);
//        assert method != null;
//        log.info("forward:{}", url);
//
//        ResponseEntity<String> response = restTemplate.exchange(url, method, entity, String.class);
//        return sanitizeResponse(response);
//    }
//
//    // PUT请求处理方法
//    @PutMapping(value = {"/system/account2"})
//    @ResponseBody
//    public ResponseEntity<String> forwardPutDataRequest(
//            @RequestHeader HttpHeaders headers,
//            @RequestBody(required = false) String requestBody,
//            HttpServletRequest request) {
//
//        HttpHeaders sanitizedHeaders = sanitizeHeaders(headers);
//        String url = getUrl(request.getServletPath());
//        HttpMethod method = HttpMethod.resolve(request.getMethod());
//        HttpEntity<String> entity = new HttpEntity<>(requestBody, sanitizedHeaders);
//        assert method != null;
//        log.info("forward:{}", url);
//
//        ResponseEntity<String> response = restTemplate.exchange(url, method, entity, String.class);
//        return sanitizeResponse(response);
//    }
//
//    // DELETE请求处理方法
//    @DeleteMapping(value = {"/system/account2/**"})
//    @ResponseBody
//    public ResponseEntity<String> forwardDeleteDataRequest(
//            @RequestHeader HttpHeaders headers,
//            @RequestBody(required = false) String requestBody,
//            HttpServletRequest request) {
//
//        HttpHeaders sanitizedHeaders = sanitizeHeaders(headers);
//        String url = getUrl(request.getServletPath());
//        HttpMethod method = HttpMethod.resolve(request.getMethod());
//        HttpEntity<String> entity = new HttpEntity<>(requestBody, sanitizedHeaders);
//        assert method != null;
//        log.info("forward:{}", url);
//
//        ResponseEntity<String> response = restTemplate.exchange(url, method, entity, String.class);
//        return sanitizeResponse(response);
//    }
//
//    // 流式POST请求处理方法
//    @PostMapping(value = {"/system/*/export", "/system/*/exportTxt"})
//    public StreamingResponseBody forwardStreamingPostRequest(
//            @RequestHeader HttpHeaders headers,
//            @RequestBody(required = false) String requestBody,
//            HttpServletRequest request) {
//
//        HttpHeaders sanitizedHeaders = sanitizeHeaders(headers);
//        String url = getUrl(request.getServletPath());
//        HttpEntity<String> entity = new HttpEntity<>(requestBody, sanitizedHeaders);
//        ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.POST, entity, byte[].class);
//        return outputStream -> {
//            outputStream.write(Objects.requireNonNull(response.getBody()));
//            outputStream.flush();
//        };
//    }
//
//    private String getUrl(String url) {
//        return targetUrl + (url.startsWith("/dev-api") ? url.replace(mapping, "") : url);
//    }
//
//    /**
//     * 增强的HTTP头清理方法 - 修复HTTP响应截断漏洞
//     */
//    private HttpHeaders sanitizeHeaders(HttpHeaders headers) {
//        HttpHeaders sanitizedHeaders = new HttpHeaders();
//
//        if (headers != null) {
//            headers.forEach((key, values) -> {
//                // 验证头名称安全性
//                if (isSafeHeaderName(key)) {
//                    values.forEach(value -> {
//                        // 严格清理头值，移除所有控制字符和CRLF
//                        String sanitizedValue = sanitizeHeaderValue(value);
//                        if (sanitizedValue != null && !sanitizedValue.isEmpty()) {
//                            // 对关键头值进行URL编码防止CRLF注入
//                            if (needsUrlEncoding(key)) {
//                                try {
//                                    sanitizedValue = URLEncoder.encode(sanitizedValue, StandardCharsets.UTF_8.name());
//                                } catch (Exception e) {
//                                    log.warn("Failed to encode header value for key: {}", key);
//                                    sanitizedValue = "";
//                                }
//                            }
//                            if (!sanitizedValue.isEmpty()) {
//                                sanitizedHeaders.add(key, sanitizedValue);
//                            }
//                        }
//                    });
//                }
//            });
//        }
//
//        // 添加安全头
//        addSecurityHeaders(sanitizedHeaders);
//        return sanitizedHeaders;
//    }
//
//    /**
//     * 验证HTTP头名称安全性
//     */
//    private boolean isSafeHeaderName(String headerName) {
//        if (headerName == null || headerName.isEmpty()) {
//            return false;
//        }
//
//        // 使用白名单验证头名称
//        return SAFE_HEADER_NAME_PATTERN.matcher(headerName).matches() &&
//                !isDangerousHeader(headerName);
//    }
//
//    /**
//     * 严格清理HTTP头值 - 修复HTTP响应截断
//     */
//    private String sanitizeHeaderValue(String value) {
//        if (value == null) {
//            return null;
//        }
//
//        // 移除所有控制字符（包括CRLF）和Unicode控制字符
//        String sanitized = value.replaceAll("[\\p{Cntrl}\\\\u0080-\\\\u009F]", "");
//
//        // 移除连续的CRLF序列
//        sanitized = sanitized.replaceAll("(\\r\\n|\\r|\\n)+", " ");
//
//        // 验证头值只包含安全字符
//        if (!SAFE_HEADER_VALUE_PATTERN.matcher(sanitized).matches()) {
//            return null; // 如果不安全，直接返回null丢弃该头值
//        }
//
//        return sanitized.trim();
//    }
//
//    /**
//     * 检查是否需要URL编码（针对易受攻击的头）
//     */
//    private boolean needsUrlEncoding(String headerName) {
//        if (headerName == null) {
//            return false;
//        }
//
//        String lowerHeader = headerName.toLowerCase();
//        // 对Cookie、Location等关键头进行编码
//        return lowerHeader.contains("cookie") ||
//                lowerHeader.contains("location") ||
//                lowerHeader.contains("set-cookie") ||
//                lowerHeader.contains("content-disposition") ||
//                lowerHeader.contains("refresh");
//    }
//
//    /**
//     * 检查危险头信息（增强版）
//     */
//    private boolean isDangerousHeader(String headerName) {
//        if (headerName == null) {
//            return true;
//        }
//
//        String lowerHeader = headerName.toLowerCase();
//        return lowerHeader.contains("crlf") ||
//                lowerHeader.contains("cr") ||
//                lowerHeader.contains("lf") ||
//                lowerHeader.contains("url") ||
//                lowerHeader.contains("script") ||
//                lowerHeader.contains("cookie") ||
//                lowerHeader.contains("set-cookie") ||
//                lowerHeader.contains("location") ||
//                lowerHeader.contains("refresh") ||
//                lowerHeader.contains("x-forwarded") ||
//                lowerHeader.contains("x-real-ip") ||
//                lowerHeader.contains("transfer-encoding");
//    }
//
//    /**
//     * 添加安全相关的HTTP头
//     */
//    private void addSecurityHeaders(HttpHeaders headers) {
//        // 使用安全的设置方法，避免直接操作原始头值
//        headers.set("X-Content-Type-Options", "nosniff");
//        headers.set("X-Frame-Options", "DENY");
//        headers.set("X-XSS-Protection", "1; mode=block");
//        headers.set("Content-Security-Policy", "default-src 'self'");
//        headers.set("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
//
//        // 确保Content-Type安全
//        if (headers.getContentType() != null) {
//            String contentType = headers.getContentType().toString();
//            if (isSafeContentType(contentType)) {
//                headers.setContentType(MediaType.parseMediaType(contentType));
//            } else {
//                headers.setContentType(MediaType.APPLICATION_JSON);
//            }
//        }
//    }
//
//    /**
//     * 验证内容类型安全性
//     */
//    private boolean isSafeContentType(String contentType) {
//        if (contentType == null || contentType.isEmpty()) {
//            return false;
//        }
//        return SAFE_CONTENT_TYPE_PATTERN.matcher(contentType).matches() &&
//                !contentType.contains("\r") &&
//                !contentType.contains("\n") &&
//                !contentType.contains("%0d") &&
//                !contentType.contains("%0a");
//    }
//
//    /**
//     * 增强的响应清理方法 - 修复HTTP响应截断
//     */
//    private ResponseEntity<String> sanitizeResponse(ResponseEntity<String> response) {
//        if (response == null) {
//            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
//        }
//
//        HttpHeaders sanitizedHeaders = new HttpHeaders();
//
//        // 严格复制和清理头信息
//        if (response.getHeaders() != null) {
//            response.getHeaders().forEach((key, values) -> {
//                if (isSafeHeaderName(key)) {
//                    values.forEach(value -> {
//                        String sanitizedValue = sanitizeHeaderValue(value);
//                        if (sanitizedValue != null && !sanitizedValue.isEmpty()) {
//                            // 对关键头进行额外编码保护
//                            if (needsUrlEncoding(key)) {
//                                try {
//                                    sanitizedValue = URLEncoder.encode(sanitizedValue, StandardCharsets.UTF_8.name());
//                                } catch (Exception e) {
//                                    log.warn("Failed to encode response header value for key: {}", key);
//                                    return; // 跳过这个头值
//                                }
//                            }
//                            sanitizedHeaders.add(key, sanitizedValue);
//                        }
//                    });
//                }
//            });
//        }
//
//        // 添加安全头
//        addSecurityHeaders(sanitizedHeaders);
//
//        // 对响应体进行HTML转义，同时防止CRLF注入
//        String sanitizedBody = response.getBody() != null ?
//                HtmlUtils.htmlEscape(response.getBody()).replaceAll("[\\r\\n]", "") : "";
//
//        return new ResponseEntity<>(sanitizedBody, sanitizedHeaders, response.getStatusCode());
//    }
//
//    /**
//     * 增强的文件下载响应构建方法
//     */
//    private ResponseEntity<Resource> buildSafeFileDownloadResponse(ResponseEntity<Resource> response) {
//        if (response == null || response.getBody() == null) {
//            return ResponseEntity.notFound().build();
//        }
//
//        HttpHeaders headers = new HttpHeaders();
//
//        // 安全设置Content-Type
//        if (response.getHeaders().getContentType() != null) {
//            String contentType = response.getHeaders().getContentType().toString();
//            if (isSafeContentType(contentType)) {
//                headers.setContentType(MediaType.parseMediaType(contentType));
//            } else {
//                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//            }
//        } else {
//            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//        }
//
//        addSecurityHeaders(headers);
//
//        // 安全处理Content-Disposition头 - 修复HTTP响应截断
//        String contentDisposition = response.getHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION);
//        if (StringUtils.hasText(contentDisposition)) {
//            String safeDisposition = sanitizeContentDisposition(contentDisposition);
//            if (safeDisposition != null) {
//                headers.set(HttpHeaders.CONTENT_DISPOSITION, safeDisposition);
//            } else {
//                headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment");
//            }
//        } else {
//            headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment");
//        }
//
//        return new ResponseEntity<>(response.getBody(), headers, response.getStatusCode());
//    }
//
//    /**
//     * 增强的Content-Disposition头清理 - 修复HTTP响应截断
//     */
//    private String sanitizeContentDisposition(String disposition) {
//        if (disposition == null) return null;
//
//        // 严格清理控制字符和CRLF
//        String sanitized = disposition.replaceAll("[\\p{Cntrl}\\\\u0080-\\\\u009F]", "");
//        sanitized = sanitized.replaceAll("(\\r\\n|\\r|\\n)+", " ");
//
//        // 验证格式
//        if (sanitized.startsWith("attachment;") || sanitized.startsWith("inline;")) {
//            // 提取filename参数并验证
//            if (sanitized.contains("filename=")) {
//                try {
//                    String filenamePart = sanitized.substring(sanitized.indexOf("filename=") + 9);
//                    // 移除引号并验证
//                    String filename = filenamePart.replaceAll("^[\"']|[\"']$", "");
//                    String safeFilename = validateAndSanitizeFilename(filename);
//                    if (safeFilename != null) {
//                        // 对文件名进行URL编码防止CRLF注入
//                        safeFilename = URLEncoder.encode(safeFilename, StandardCharsets.UTF_8.name());
//                        return "attachment; filename=\"" + safeFilename + "\"";
//                    }
//                } catch (Exception e) {
//                    log.warn("Failed to process content-disposition header", e);
//                }
//            }
//            return "attachment";
//        }
//
//        return "attachment";
//    }
//
//    /**
//     * 文件名验证和清理（增强版）
//     */
//    private String validateAndSanitizeFilename(String filename) {
//        if (!StringUtils.hasText(filename)) {
//            return "file";
//        }
//
//        // 移除控制字符和CRLF
//        String sanitized = filename.replaceAll("[\\p{Cntrl}\\\\r\\\\n]", "");
//
//        if (!SAFE_FILENAME_PATTERN.matcher(sanitized).matches()) {
//            return null;
//        }
//
//        if (sanitized.contains("..") || sanitized.contains("/") || sanitized.contains("\\")) {
//            return null;
//        }
//
//        return sanitized;
//    }
//}